//
// Created by none98 on 2021/9/16.
//

#include <spdlog/spdlog.h>
#include "Dispatcher.h"
#include "Service.h"
#include "TcpConnection.h"

void Dispatcher::RegisterHandler(unsigned int type, Service* handler){
    if(handlers.find(type)!=handlers.end()){
        spdlog::error("handler {} existed!",type);
    }else{
        handlers[type]=std::move(std::unique_ptr<Service>(handler));
    }
}

/*
 * struct ProtoPackage{
 *  int length;
 *  int type;
 *  char [protobufdata];
 * }
 *
 *
 * */

void Dispatcher::Dispatch(TcpConnectionPtr conn, Buffer *inputBuffer) {
    try{
        if(inputBuffer->ReadableSize()<4) return;
        else if(inputBuffer->ReadableSize()>=4){
            std::string head;
            inputBuffer->Read(head,4);
            int length = (head[0]<<24)|(head[1]<<16)|(head[2]<<8)|head[3];
            if(inputBuffer->ReadableSize()<length-4)
                return;
            else{
                head.clear();
                inputBuffer->Read(head,4);
                int type = (head[0]<<24)|(head[1]<<16)|(head[2]<<8)|head[3];
                head.clear();
                inputBuffer->Read(head,length-8);
                submiter(std::bind(&Service::Serve,handlers[type].get(),conn,std::move(head)));
            }
        }
    }catch(std::invalid_argument in){
        spdlog::error("{}",in.what());
        conn->Close();

    }catch(std::out_of_range out){
        spdlog::error("{}",out.what());
        conn->Close();
    }
}
